package com.yanqu.road.logic.xlogic.rank.channel.entiety;

import com.yanqu.road.entity.rank.xrank.XChannelRankPart;
import com.yanqu.road.logic.bussiness.rank.XRankBussiness;
import com.yanqu.road.logic.xlogic.rank.base.AbstractXRankListModel;
import com.yanqu.road.utils.string.StringUtils;

import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

public class XChannelPartListModel extends AbstractXRankListModel {

    private int maxRank;
    private Comparator<XChannelRankPart> rankSort;
    private LinkedList<XChannelRankPart> rankList = new LinkedList<>();
    private int rankCapacity;

    private long allSyncTime;

    public XChannelPartListModel(String dbName, String tableName,
                                 int maxRank, Comparator<XChannelRankPart> rankSort) {
        super(dbName, tableName);

        this.maxRank = maxRank;
        this.rankSort = rankSort;

        this.rankCapacity = calcRankCapacity(maxRank);
    }

    private int calcRankCapacity(int maxRank) {
        return maxRank + 20;
    }

    public void setMaxRank(int maxRank) {
        this.maxRank = maxRank;
        this.rankCapacity = calcRankCapacity(maxRank);
    }

    /**
     * 获取排名
     *
     * @param rankList 超出这个的长度排名为-1
     */
    private XGetChannelRankPartResult getMyRankResult(long userId, List<XChannelRankPart> rankList) {
        int rank = 0;
        for (XChannelRankPart rankPart : rankList) {
            rank++;
            if (rankPart.getUserId() == userId) {
                return new XGetChannelRankPartResult(rankPart, rank);
            }
        }
        return new XGetChannelRankPartResult();
    }

    public int getMyRank(long userId) {
        return getMyRankResult(userId, getRankList()).getMyRank();
    }

    public XChannelRankPartChangeResult rankChange(XChannelRankPart rankPart, XChannelRankPartChangeParam param) {
        synchronized (this) {

            boolean isChange = false;
            boolean inList = false;
            XGetChannelRankPartResult oldRankResult = getMyRankResult(rankPart.getUserId(), rankList);
            XChannelRankPart oldUserRank = oldRankResult.getRankPart();

            // 更新请求参数
            if (oldUserRank != null) {
                // 昵称有增量用增量
                rankPart.setNickname(
                        param.isUpdateNickname() && StringUtils.isNullOrEmpty(rankPart.getNickname()) ?
                                oldUserRank.getNickname()
                                : rankPart.getNickname());
                // 值没变化不改更新时间
                rankPart.setUpdateTime(rankSort.compare(rankPart, oldUserRank) != 0 ? rankPart.getUpdateTime() : oldUserRank.getUpdateTime());
            }

            // 有旧的就替换
            if (oldUserRank != null) {
                oldUserRank.replace(rankPart);
                inList = true;
                isChange = true;
            }

            // 能否新上榜
            if (!inList) {
                if (rankList.size() < rankCapacity) {
                    rankList.add(rankPart.clone());
                    isChange = true;
                } else {
                    XChannelRankPart lastRank = rankList.getLast();
                    if (rankSort.compare(lastRank, rankPart) > 0) {
                        rankList.removeLast();
                        rankList.add(rankPart.clone());
                        isChange = true;
                    }
                }
            }

            // 处理结果
            if (isChange) {
                rankList.sort(rankSort);
                int newRank = getMyRankResult(rankPart.getUserId(), rankList).getMyRank();
                addDbRank(oldRankResult.getMyRank(), newRank, rankCapacity);
            }

            // 记录结果
            XChannelRankPartChangeResult result = new XChannelRankPartChangeResult();
            result.setChange(isChange);
            result.setNewInRank(isChange && !inList);
            return result;
        }
    }

    public void initByRankList(LinkedList<XChannelRankPart> rankList) {
        synchronized (this) {
            this.rankList = rankList;
            this.rankList.sort(rankSort);
            // 去掉多余的
            while (this.rankList.size() > rankCapacity) {
                this.rankList.removeLast();
            }
        }
    }

    public List<XChannelRankPart> getRankList() {
        return getRankList(maxRank);
    }

    public List<XChannelRankPart> getRankList(int maxCount) {
        List<XChannelRankPart> list = new LinkedList<>();
        for (XChannelRankPart rank : new LinkedList<>(rankList)) {
            list.add(rank);
            if (list.size() >= maxCount) {
                break;
            }
        }
        return list;
    }

    public int getMaxRank() {
        return maxRank;
    }

    public Comparator<XChannelRankPart> getRankSort() {
        return rankSort;
    }

    public long getAllSyncTime() {
        return allSyncTime;
    }

    public void setAllSyncTime(long allSyncTime) {
        this.allSyncTime = allSyncTime;
    }

    @Override
    public void save() {
        List<XChannelRankPart> tmpRankList;
        Set<Integer> dbRankSet;
        synchronized (this) {
            tmpRankList = new LinkedList<>(rankList);
            dbRankSet = getAndClearAllDbRank();
        }
        // 根据dbName和tableName入库
        XRankBussiness.replaceXChannelRankPart(dbName, tableName, tmpRankList, dbRankSet);
    }

}
